package org.jackysoft.report;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jackysoft.entity.ArmItem;
import org.jackysoft.entity.DataItem;
import org.jackysoft.entity.ProductType;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

@Component
public final class DataItemUtil {
	/**
	 * 获取数据项列
	 * 
	 * @param ai
	 *            数据行
	 * @param dt
	 *            列类型枚举
	 * @return 数据列项
	 * */
	public DataItem getDataItem(ArmItem ai, DataItemType dt) {
		return ai.getDataItems().get(dt.toString());
	}

	/**
	 * 取得数据项原子值
	 * 
	 * @param ai
	 *            数据项
	 * @param dt
	 *            数据类型
	 * @return 返回值 0d 如果没有找到
	 * */
	public Double getDataItemAtom(ArmItem ai, DataItemType dt) {
		DataItem di = ai.getDataItems().get(dt.toString());
		return di == null ? 0d : di.getAtomValue();
	}

	/**
	 * 取得数据项累计值
	 * 
	 * @param ai
	 *            数据项
	 * @param dt
	 *            数据类型
	 * @return 返回值 0d 如果没有找到
	 * */
	public Double getDataItemAccumulation(ArmItem ai, DataItemType dt) {
		DataItem di = ai.getDataItems().get(dt.toString());
		return di == null ? 0d : di.getAccumulateValue();
	}

	/**
	 * 创建一个数据项
	 * */
	public DataItem createDataItem(DataItemType dt) {
		DataItem d = new DataItem();
		d.setLabel(dt.toString());
		return d;
	}

	/**
	 * 为一个数据项添加数据列
	 * */
	public void appendDataItems(ArmItem ai, Set<DataItemType> dts) {
		for (DataItemType dt : dts) {
			ai.getDataItems().put(dt.toString().toLowerCase(),
					createDataItem(dt));
		}
	}

	public void setDataItemValue(ArmItem ai, DataItemType dt, Double val,
			Double aclVal) {
		if (ai == null)
			return;

		DataItem di = ai.getDataItems().get(dt.toString());
		if (di == null) {
			di = new DataItem();
			ai.getDataItems().put(dt.toString(), di);
		}
		di.setAtomValue(val);
		di.setAccumulateValue(aclVal);

	}

	public void setDataItem(ArmItem ai, DataItemType dt, DataItem di) {
		if (ai == null || di==null)return;
		
        ai.getDataItems().put(dt.toString(), di);   
	}

	/**
	 * 
	 * Map操作,把数据映射为Map
	 * 以产品类型作为Key，进行映射
	 * @param items
	 *            所有数据项
	 * */
	public Map<ProductType, Collection<ArmItem>> mapArmItems(
			Collection<ArmItem> items) {
		if (CollectionUtils.isEmpty(items))
			return Collections.emptyMap();
		Map<ProductType, Collection<ArmItem>> mapItems = Maps.newHashMap();
		for (ArmItem item : items) {
			if (item == null)
				continue;
			Collection<ArmItem> citems = mapItems.get(item.getItemType());
			if (citems == null) {
				citems = Lists.newArrayList();
				mapItems.put(item.getItemType(), citems);
			}
			citems.add(item);
		}

		return mapItems;

	}

	/**
	 * 把每个key对应的数据合并
	 * 对业务数据而言就是产品编码，例如报表
	 * 在同一个类型区域内相同编码的产品如果报了两次
	 * 视作同一个产品
	 * @param items
	 * */
	public Collection<ArmItem> reduceArmItems(Collection<ArmItem> items) {
		if (CollectionUtils.isEmpty(items))
			return Collections.emptyList();
		Collection<ArmItem> dests = Lists.newArrayList();
		// key 产品ID, List报表数据项
		Map<String, List<ArmItem>> temp = Maps.newHashMap();
		for (ArmItem ai : items) {
			if (ai == null)
				continue;
			String pcode = ai.getHost().getCode();
			if (temp.get(pcode) == null) {
				temp.put(pcode, new ArrayList<ArmItem>());
			}
			temp.get(pcode).add(ai);
		}
		for (String key : temp.keySet()) {
			if (temp.get(key).size() > 1) {
				ArmItem item = mergeArmItemList(temp.get(key));
				if (item != null)
					dests.add(item);
			} else {
				dests.add(temp.get(key).get(0));
			}

		}

		return dests;
	}

	/**
	 * 合并相同的数据项 依据是对应产品编码相同 此函数相当于reduce
	 * 
	 * @param items
	 *            综合数据项
	 * 
	 * */
	public Collection<ArmItem> mergeArmItems(Collection<ArmItem> items) {
		if (CollectionUtils.isEmpty(items))
			return Collections.emptyList();
		Collection<ArmItem> myItems = Lists.newArrayList();
		Map<ProductType, Collection<ArmItem>> maps = mapArmItems(items);
		for (Map.Entry<ProductType, Collection<ArmItem>> entry : maps
				.entrySet()) {
			myItems.addAll(reduceArmItems(entry.getValue()));
		}
		return myItems;

	}
	/**
	 * 合并相同的数据项 依据是对应产品编码相同 此函数相当于reduce
	 * 
	 * @param items
	 *            综合数据项
	 * 
	 * */
	public  Map<ProductType, Collection<ArmItem>> mergeArmItemMap(Collection<ArmItem> items) {
		if (CollectionUtils.isEmpty(items))return Collections.emptyMap();
		Map<ProductType, Collection<ArmItem>> myItems = Maps.newHashMap();
		Map<ProductType, Collection<ArmItem>> maps = mapArmItems(items);
		for (Map.Entry<ProductType, Collection<ArmItem>> entry : maps
				.entrySet()) {
			myItems.put(entry.getKey(), reduceArmItems(entry.getValue()));
		}
		return myItems;
		
	}

	protected ArmItem mergeArmItemList(List<ArmItem> list) {
		if (null == list)
			return null;
		ArmItem aim = list.get(0);
		if (list.size() == 1)
			return aim;
		list.remove(0);
		for (ArmItem source : list)
			aim = mergeArmItem(source, aim);
		return aim;
	}

	/**
	 * @return target
	 * */
	protected ArmItem mergeArmItem(ArmItem source, ArmItem target) {
		Map<String, DataItem> targetDatas = target.getDataItems();
		Map<String, DataItem> sourceDatas = source.getDataItems();
		for (String key : targetDatas.keySet()) {
			DataItem targetdata = targetDatas.get(key);
			DataItem sourcedata = sourceDatas.get(key);
			targetdata.setAtomValue(targetdata.getAtomValue()
					+ sourcedata.getAtomValue());
			targetdata.setAccumulateValue(targetdata.getAccumulateValue()
					+ sourcedata.getAccumulateValue());
		}
		target.setRemark(target.getRemark() + "\n" + source.getRemark());

		return target;
	}

}
